package com.kaibes.platform.file.server;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.kaibes.core.base.annotation.Description;
import com.kaibes.module.file.local.FileLocalService;
import com.kaibes.module.file.local.MD5String;
import com.kaibes.module.file.local.api.FileLocalApi;
import com.kaibes.module.file.local.db.FileMarkService;
import com.kaibes.module.file.local.to.PreloadTO;
import com.kaibes.module.file.local.to.UploadTO;
import com.kaibes.web.api.ApiLink;
import com.kaibes.web.response.ResponseFactory;

@RestController
@RequestMapping("/encrypts/files")
@CrossOrigin
public class FileEncryptApi {

    @Autowired
    private FileLocalApi fileLocalApi;
    @Autowired
    private FileClientService fileClientService;
    @Autowired
    private FileMarkService fileMarkService;
    @Autowired
    private FileTokenHelper fileTokenHelper;
    @Autowired
    private FileLocalService fileLocalService;
    
    @GetMapping("/test/{userId}/{hello}")
    @ApiLink(value = "测试验证", validated = false)
    public ResponseEntity<Object> test(@PathVariable @Description("用户ID") Integer userId, @PathVariable String hello ) {
        FileClient fileClient = fileClientService.findByUserId(userId);
        if (fileClient == null) {
        	return ResponseFactory.getFailure("请求失败！");
        }
        hello = fileTokenHelper.readString(fileClient, hello);
        if (hello == null) {
        	return ResponseFactory.getFailure("请求失败！");
        }
        return ResponseFactory.getSuccess(hello);
    }
    
    @PostMapping("/upload/{userId}")
    @ApiLink(value = "上传文件", validated = false)
    public ResponseEntity<UploadTO> upload(@PathVariable @Description("用户ID") Integer userId,
            @RequestParam @Description("MD5密文") String ciphertext,
            @RequestParam(name = "file") @Description("文件") MultipartFile file) {

        FileClient fileClient = fileClientService.findByUserId(userId);
        UploadTO uploadTO = new UploadTO();
        if (fileClient == null) {
            uploadTO.setMsg("非法请求，未知用户");
            return ResponseFactory.postFailure(uploadTO);
        }

        String md5 = fileTokenHelper.readString(fileClient, ciphertext);
        if (md5 == null) {
            uploadTO.setMsg("非法请求，md5不存在或密钥错误");
            return ResponseFactory.postFailure(uploadTO);
        }

        return fileLocalService.upload(userId, file, md5);
    }

    @PostMapping("/preload/{userId}")
    @ApiLink(value = "文件预上传，如果文件已存在会返回文件信息，否则返回文件不存在的提示", validated = false)
    public ResponseEntity<PreloadTO> preupload(@PathVariable @Description("用户ID") Integer userId,
            @RequestBody @Description("加密后的MD5") MD5String md5String) {
        FileClient fileClient = fileClientService.findByUserId(userId);
        PreloadTO resultTO = new PreloadTO();
        if (fileClient == null) {
            resultTO.setFlag(false);
            resultTO.setMsg("非法请求，未知用户");
            return ResponseFactory.postFailure(resultTO);
        }
        String md5 = fileTokenHelper.readString(fileClient, md5String.getMd5());
        if (md5 == null) {
            resultTO.setMsg("非法请求，md5不存在或密钥错误");
            return ResponseFactory.postFailure(resultTO);
        }
        md5String = new MD5String();
        md5String.setMd5(md5);
        return fileLocalApi.preUpload(userId, md5String);
    }

    @GetMapping("/{uuid}")
    @ApiLink(value = "获取文件，返回值是字节流", validated = false)
    public void get(HttpServletRequest request, HttpServletResponse response,
            @PathVariable @Description("文件的UUID") String uuid) {
        fileLocalApi.getByUuid(request, response, uuid);
    }
    
    @GetMapping("/list/{uuid}")
    @ApiLink(value = "获取压缩文件长度", validated = false)
    public ResponseEntity<Object> get(@PathVariable @Description("文件的UUID") String uuid) {
        if (uuid.contains(".")) {
            uuid = uuid.split("\\.")[0];
        }
        File[] files = fileLocalService.unZip(uuid);
        HashMap<String, Integer> map = new HashMap<>(1);
        if (files != null) {
        	map.put("length", files.length);
        } else {
        	map.put("length", 0);
        }
        return ResponseFactory.getSuccess(map);
    }
    
    @GetMapping("/{uuid}/{name}")
    @ApiLink(value = "获取文件，返回值是字节流", validated = false)
    public void get(HttpServletRequest request, HttpServletResponse response,
            @PathVariable @Description("文件的UUID") String uuid,
            @PathVariable @Description("压缩包里文件名或位置") String name) {
        fileLocalApi.getByUuid(request, response, uuid, name);
    }
    
    @DeleteMapping("/{userId}")
    @ApiLink(value = "删除文件", validated = false)
    public ResponseEntity<Object> deleteInPath(@PathVariable @Description("用户ID") Integer userId, 
            @RequestBody @Description("UUID数组加密") Map<String, String> uuids) {
        FileClient fileClient = fileClientService.findByUserId(userId);
        try {
        	List<String> uuidList = fileTokenHelper.readListString(fileClient, uuids.get("uuids"));
        	if (uuidList == null) {
                return ResponseFactory.deleteFailure("删除文件失败！");
            }
            fileMarkService.removeByUuidIn(uuidList);
            return ResponseFactory.deleteSuccess("删除文件成功");
		} catch (Exception e) {
			return ResponseFactory.deleteFailure("删除文件失败！");
		}
    }

}
